}
break;
- case INSTR_MOVZ:
+ case INSTR_MOVZX:
if (dst & REGISTER) {
+ switch (size) {
+ case BYTE:
+ p->u.data &= 0xFFULL;
+ break;
+
+ case WORD:
+ p->u.data &= 0xFFFFULL;
+ break;
+
+ case LONG:
+ p->u.data &= 0xFFFFFFFFULL;
+ break;
+
+ default:
+ printk("Impossible source operand size of movzx instr: %d\n", size);
+ domain_crash_synchronous();
+ }
index = operand_index(dst);
+ set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
+ }
+ break;
+
+ case INSTR_MOVSX:
+ if (dst & REGISTER) {
switch (size) {
- case BYTE: p->u.data = p->u.data & 0xFFULL; break;
- case WORD: p->u.data = p->u.data & 0xFFFFULL; break;
- case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break;
+ case BYTE:
+ p->u.data &= 0xFFULL;
+ if ( p->u.data & 0x80ULL )
+ p->u.data |= 0xFFFFFFFFFFFFFF00ULL;
+ break;
+
+ case WORD:
+ p->u.data &= 0xFFFFULL;
+ if ( p->u.data & 0x8000ULL )
+ p->u.data |= 0xFFFFFFFFFFFF0000ULL;
+ break;
+
+ case LONG:
+ p->u.data &= 0xFFFFFFFFULL;
+ if ( p->u.data & 0x80000000ULL )
+ p->u.data |= 0xFFFFFFFF00000000ULL;
+ break;
+
+ default:
+ printk("Impossible source operand size of movsx instr: %d\n", size);
+ domain_crash_synchronous();
}
+ index = operand_index(dst);
set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
}
break;
}
switch (*++opcode) {
- case 0xB6: /* movz m8, r16/r32 */
- instr->instr = INSTR_MOVZ;
+ case 0xB6: /* movzx m8, r16/r32/r64 */
+ instr->instr = INSTR_MOVZX;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
index = get_index(opcode + 1, rex);
instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
return DECODE_success;
- case 0xB7: /* movz m16/m32, r32/r64 */
- instr->instr = INSTR_MOVZ;
+ case 0xB7: /* movzx m16/m32, r32/r64 */
+ instr->instr = INSTR_MOVZX;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
index = get_index(opcode + 1, rex);
- if (rex & 0x8) {
- instr->op_size = LONG;
- instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
- } else {
- instr->op_size = WORD;
- instr->operand[1] = mk_operand(LONG, index, 0, REGISTER);
- }
- instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
+ if (rex & 0x8)
+ instr->operand[0] = mk_operand(LONG, 0, 0, MEMORY);
+ else
+ instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
+ instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ return DECODE_success;
+
+ case 0xBE: /* movsx m8, r16/r32/r64 */
+ instr->instr = INSTR_MOVSX;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ index = get_index(opcode + 1, rex);
+ instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
+ instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ return DECODE_success;
+
+ case 0xBF: /* movsx m16, r32/r64 */
+ instr->instr = INSTR_MOVSX;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ index = get_index(opcode + 1, rex);
+ instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
+ instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
return DECODE_success;
case 0xA3: /* bt r32, m32 */
send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0);
} else if (inst->operand[0] & MEMORY) { /* dest is register */
/* send the request and wait for the value */
- if (inst->instr == INSTR_MOVZ)
+ if ( (inst->instr == INSTR_MOVZX) || (inst->instr == INSTR_MOVSX) )
send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, 0);
else
send_mmio_req(type, gpa, 1, inst->op_size, 0, IOREQ_READ, 0);
break;
}
- case INSTR_MOVZ:
+ case INSTR_MOVZX:
+ case INSTR_MOVSX:
mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs);
break;